package com.zhuj.client;

import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.zhuj.codec.NrpcJsonDecode;
import com.zhuj.codec.NrpcJsonEncode;
import com.zhuj.codec.NrpcProtostuffDecode;
import com.zhuj.codec.NrpcProtostuffEncode;
import com.zhuj.core.Global;
import com.zhuj.core.InitNrpc;
import com.zhuj.core.entity.ClientRequest;
import com.zhuj.handler.ClientHandler;
import com.zhuj.logic.ProcessRunnable;
import com.zhuj.register.Register;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

/**
 * Created by Administrator on 2018/1/3.
 */
public class NrpcClient {

    private static final Logger LOG = LoggerFactory.getLogger(NrpcClient.class);

    public static ProcessRunnable processRunnable = new ProcessRunnable();

    private Bootstrap bootstrap;

    private NioEventLoopGroup group;

    public NrpcClient(){
        group = new NioEventLoopGroup();
        bootstrap = new Bootstrap();
        bootstrap.group(group)
             .channel(NioSocketChannel.class)
             .handler(new ChannelInitializer<SocketChannel>() {
                 protected void initChannel(SocketChannel socketChannel) throws Exception {
                     ChannelPipeline pipeline = socketChannel.pipeline();
//                     pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
                     if ("json".equals(InitNrpc.getCodec())){
                         pipeline.addLast(new StringDecoder());
                         pipeline.addLast(new LineBasedFrameDecoder(64*1024));
                         pipeline.addLast(new NrpcJsonDecode(true));
                         pipeline.addLast(new StringEncoder());
                         pipeline.addLast(new NrpcJsonEncode());
                     }else if ("protobuf".equals(InitNrpc.getCodec())){
                         pipeline.addLast(new NrpcProtostuffDecode(true));
                         pipeline.addLast(new NrpcProtostuffEncode());
                     }
                     pipeline.addLast(new ClientHandler());
                 }
             });
    }

    public Channel start(String address,int port){
        try {
            ChannelFuture future = bootstrap.connect(address,port).sync();
            LOG.info("nrpc client connect to:"+address+":"+port);
            return future.channel();
        } catch (InterruptedException e) {
            LOG.info("client start to"+address+":"+port+" error,Info : "+e.getMessage());
        }
        return null;
    }

    public void close(){
        group.shutdownGracefully();
    }

    public static void sendRequest(ClientRequest request){
        Channel channel = Global.getClientChannel(request.getService());
        if (channel==null || !channel.isActive()){
            if (InitNrpc.getAddress() == null) {
                Map.Entry<String, Integer> entry = Register.getServiceUrl(request.getService());
                channel = InitNrpc.getClient().start(entry.getKey(), entry.getValue());
            }else {
                channel = InitNrpc.getClient().start(InitNrpc.getAddress(),InitNrpc.getPort());
            }
            Global.setClientChannel(request.getService(),channel);
        }
        channel.writeAndFlush(request);
    }

}
